package com.study.lxy.springcloud.cardman.service.impl;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.study.lxy.springcloud.cardman.dao.CardNoDao;
import com.study.lxy.springcloud.cardman.service.GenCardNoService;
import com.study.lxy.springcloud.cardman.utils.RespCodeEnum;
import com.study.lxy.springcloud.common.exception.BusiException;
import com.study.lxy.springcloud.common.utils.RedisUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Component
public class GenCardNoServiceImpl implements GenCardNoService {

    private static final Logger logger = LoggerFactory.getLogger(GenCardNoServiceImpl.class);

    @Autowired
    private CardNoDao cardNoDao;
    @Autowired
    private RedisUtils redisUtils;
    private LoadingCache<String,String> cardBinCache;

    public GenCardNoServiceImpl(){
        CacheLoader<String,String> cardBinLoader = new CacheLoader<String, String>() {
            @Override
            public String load(String s) throws Exception {
                String[] params = s.split("&");
                if(params.length != 2){
                    throw new BusiException(RespCodeEnum.CARD_BUSI_EMPTY);
                }
                logger.info("query CardBin from database,key={}",s);
                return cardNoDao.queryCardBin(params[0],params[1]);
            }
        };
        cardBinCache = CacheBuilder.newBuilder()
                .maximumSize(1000)
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .build(cardBinLoader);
    }

    @Override
    public String generateCardNo(String cardType, String busiType) {
        vaildateParams(cardType,busiType);
        try {
            String cardBin = cardBinCache.get(cardType + "&" + busiType);
            if(cardBin == null){
                throw new BusiException(RespCodeEnum.CARD_BUSI_INVILD);
            }
            String redisKey = "cardSeq" + ":" + cardBin;
            long cardSeq = redisUtils.incr(redisKey,1);
            String seqStr = String.format("%010d",cardSeq);
            return cardBin + seqStr;
        } catch (BusiException ex){
            throw ex;
        } catch(Exception e){
            logger.error("generateCardNo error",e);
            throw new BusiException(RespCodeEnum.COMMON_ERROR);
        }
    }

    private void vaildateParams(String cardType,String busiType){

        if(StringUtils.isEmpty(cardType)){
            throw new BusiException(RespCodeEnum.PARAM_INVAILD,"卡类型必输");
        }

        if(StringUtils.isEmpty(busiType)){
            throw new BusiException(RespCodeEnum.PARAM_INVAILD,"业务类型必输");
        }

    }

}
